#pragma once
#include <string>
#include <unordered_map>
#include <memory>
#include <sstream>
#include "Socket.hpp"
#include "InetAddr.hpp"
#include "Log.hpp"
#include "Util.hpp"

using namespace SocketModule;
using namespace LogModule;

const std::string gspace = " ";        // 请求行空格
const std::string glinespace = "\r\n"; // 换行符
const std::string gsep = ": ";         // 请求报头的kv分隔符

const std::string gwebroot = "./wwwroot";
const std::string ghomepage = "index.html";
const std::string gnfindpage = "404.html";

class HttpRequest
{
public:
    HttpRequest() : _blankline(glinespace)
    {
    }

    // req_line: GET空格/空格HTTP/1.1\r\n
    void PraseReqLine(const std::string &req_line)
    {
        std::stringstream ss(req_line);
        ss >> _method >> _uri >> _version;
    }

    bool Deserialize(const std::string &in)
    {
        // 解析请求行
        size_t pos = in.find(glinespace);
        if (pos == std::string::npos)
            return false;
        std::string req_line = in.substr(0, pos);
        // 设置请求参数
        PraseReqLine(req_line);
        LOG(LogLevel::INFO) << "method:" << _method;
        LOG(LogLevel::INFO) << "uri:" << _uri;
        LOG(LogLevel::INFO) << "version:" << _version;

        if (_uri == "/")
            _uri = gwebroot + _uri + ghomepage; // ./wwwroot + /index.html
        else
            _uri = gwebroot + _uri; // ./wwwroot + /a/b/c.html

        return true;
    }
    std::string Uri() { return _uri; }

    ~HttpRequest()
    {
    }

    // public:
private:
    std::string _method;  // 请求方法
    std::string _uri;     // uri（资源标识符），资源路径
    std::string _version; // HTTP版本
    std::unordered_map<std::string, std::string> _headers;

    std::string _blankline; // 空行
    std::string _text;      // 正文数据，有效载荷
};

class HttpResonse
{
public:
    HttpResonse() : _blankline(glinespace) {}
    std::string Serialize()
    {
        // 字符串拼接
        std::string result = _version + gspace + std::to_string(_code) + gspace + _description + glinespace;
        for (auto &header : _headers)
        {
            result += header.first + gsep + header.second + glinespace;
        }
        result += _blankline + _text;
        return result;
    }
    void SetCode(int code)
    {
        _code = code;
        switch (code)
        {
        case 404:
            _description = "Not Found";
            break;
        case 200:
            _description = "OK";
            break;
        default:
            _description = "Not Known";
            break;
        }
    }
    void SetHeader(const std::string key, const std::string value)
    {
        _headers.emplace(key, value);
    }

    std::string GetContentType(const std::string &filepath)
    {
        auto pos = filepath.rfind(".");
        if (pos == std::string::npos)
            return "";

        std::string suffix = filepath.substr(pos);
        if (suffix == ".html")
            return "text/html";
        else if (suffix == ".jpg")
            return "image/jpeg";
        else if (suffix == ".png")
            return "image/png";

        return "";
    }

    void MakeResponse(const std::string &filepath)
    {
        _version = "HTTP/1.1";
        int filesize = Util::ReadFileContent(filepath, _text);
        if (filesize < 0)
        {
            SetCode(404);
            LOG(LogLevel::INFO) << "要访问的资源不存在：" << filepath;
            int nfpagesize = Util::ReadFileContent(gnfindpage, _text);
            SetHeader("Content-Length", std::to_string(nfpagesize));
            SetHeader("Content-Type", "text/html");
        }
        else
        {
            SetCode(200);
            SetHeader("Content-Length", std::to_string(filesize));
            SetHeader("Content-Type", GetContentType(filepath));
        }
    }

    ~HttpResonse() {}

    // private:
public:
    std::string _version;     // Http版本
    int _code;                // 状态码
    std::string _description; // 状态码描述
    std::unordered_map<std::string, std::string> _headers;

    std::string _blankline;
    std::string _text;
};

class Http
{
public:
    Http()
    {
    }
    void GetRequest(std::shared_ptr<Socket> sock, const InetAddr &addr)
    {
        // 1.接受请求
        std::string data;
        bool success = sock->Recv(data);
        if (success)
        {
            std::cout << "******************************" << std::endl;
            std::cout << data;
            std::cout << "******************************" << std::endl;

            // 2.1 验证请求完整性，略
            // 2.2 反序列化
            HttpRequest req;
            bool success = req.Deserialize(data);

            // 3.处理请求，返回结果
            std::string filepath = req.Uri();
            HttpResonse resp;
            resp.MakeResponse(filepath);

            // 4.序列化结果
            std::string result = resp.Serialize();

            // 5.返回响应
            ssize_t n = sock->Send(result);
            (void)n;
        }
    }

    ~Http()
    {
    }
};